	coroutine = function(func) {
	return function() {	
		if (suspendedFrame && suspendedFrame._r.thread == currentThread && suspendedFrame._r.func) {
				var frame = suspendedFrame;
				var gen = frame._r;
				delete gen.thread;
	
				suspendedFrame = gen.childFrame; // if this is undefined it means we are at the top of the resume stack
				delete gen.childFrame; // for assertions
				var result = suspendedFrame._r.func(); // resume the stack
				if (result == Suspend) return frame._s(); // if we have to suspend again right away
		}
		else { //fresh entry
			var gen = func.apply(this,arguments);
			if (!(gen != null && typeof(gen) == "object" &&
					typeof(gen.next) == "function" && typeof(gen.send) == "function"))
				return gen;
			var frame = new CallFrame;
			frame._r = gen;
			frame._r.func = arguments.callee;
			var result;
		}
		try{
			while(1){
				coreturn = undefined; // global return value
				result = gen.send(result);
				if (result == Suspend) return frame._s();
			} 
		} catch(e if e == StopIteration) {
			return coreturn;
		}		
	}
}




sleep = coroutine(function(milliseconds) {
	var future = new Future();
	setTimeout(future.fulfill,milliseconds);
	yield future.result();
});
test = coroutine(function() {
		console.log('test start');
		yield sleep(3000);
		console.log('after three seconds');
		coreturn = 5;return;
});
runtest = coroutine(function() {

		var future = new Future(test);
		yield sleep(1500);
		console.log('after 1.5 seconds');
		var a = yield future.result(); 
		console.log('result from test ' + a);
		coreturn = 5;return;
})


